<?php
	/**
	 * @package AmpleHarvest
	 */
	/**
	 * @brief This Class is used build / store a solr query
	 *
	 * - Revision History
	 *  - 0.1
	 * 	 - <b>Date</b>: 31 MAR 2011
	 * 	 - <b>Author</b>: Randy Blancett
	 * 	  - Initial Version
	 *
	 * @author Randy Blancett
	 * @version 0.1
	 * @ingroup code classes
	 */
	class cSolrQuery
	{
		const C_STR_QUERY_DEFAULT = "";

		const C_STR_QUERY_JOIN_AND = "AND";
		const C_STR_QUERY_JOIN_OR = "OR";

		const C_STR_QUERY_TYPE_CONDITION = "condition";
		const C_STR_QUERY_TYPE_GROUP = "group";

		const C_STR_QUERY_CONDITION_EQUALS = "==";
		const C_STR_QUERY_CONDITION_NOT = "!=";

		const C_STR_QUERY_FIELD = "field";
		const C_STR_QUERY_VALUE = "value";
		const C_STR_QUERY_JOIN = "join";
		const C_STR_QUERY_TYPE = "type";
		const C_STR_QUERY_CONDITION = "condition";
		const C_STR_QUERY_CHILDREN = "children";

		const C_STR_FORMAT_DATE = "Y-m-d\TH:i:s\Z";

		protected $arr_Query = array();

		protected $m_obj_InsertPoint = null;
		protected $m_arr_FamlyTree = null;

		public function __construct()
		{
			$this->m_obj_InsertPoint =& $this->arr_Query;
			$this->m_arr_FamlyTree[] =& $this->arr_Query;
		}

		protected function prep_Input($str_Input)
		{
			$str_Input = str_replace("\\\"", "\"", $str_Input);

			return $str_Input;
		}

		public function start_Group($str_Join = self::C_STR_QUERY_JOIN_AND)
		{
			$int_I = sizeof($this->arr_Query);
			$this->arr_Query[$int_I] = array();
			$this->arr_Query[$int_I][self::C_STR_QUERY_TYPE] = self::C_STR_QUERY_TYPE_GROUP;
			$this->arr_Query[$int_I][self::C_STR_QUERY_JOIN] = $str_Join;
			$this->arr_Query[$int_I][self::C_STR_QUERY_CHILDREN] = array();

			$this->m_obj_InsertPoint =& $this->arr_Query[$int_I][self::C_STR_QUERY_CHILDREN];
			$this->m_arr_FamlyTree[] =& $this->arr_Query[$int_I][self::C_STR_QUERY_CHILDREN];
		}

		public function end_Group()
		{
			$int_I = sizeof($this->m_arr_FamlyTree);
			if ($int_I > 1)
			{
				array_pop($this->m_arr_FamlyTree);
				$this->m_obj_InsertPoint =& $this->m_arr_FamlyTree[sizeof($this->m_arr_FamlyTree) - 1];
			}
		}

		public function isActive()
		{
			if (sizeof($this->arr_Query) > 0)
			{
				return true;
			}
			return false;
		}

		public function clear()
		{
			$this->arr_Query = array();
		}

		public function add_Query($str_Input, $str_Field = false, $str_Condition = self::C_STR_QUERY_CONDITION_EQUALS, $str_Join = self::C_STR_QUERY_JOIN_AND)
		{
			$str_Input = $this->prep_Input($str_Input);
			$str_Join = trim($str_Join);

			$arr_Tmp = array();

			if (!$str_Input)
			{
				return;
			}

			if ($str_Field)
			{
				$str_Field = trim($str_Field);
				if (strpos($str_Input, " " . self::C_STR_QUERY_JOIN_AND . " ") !== false)
				{
					$arr_Input = explode(" " . self::C_STR_QUERY_JOIN_AND . " ", $str_Input);
					$int_I = 0;
					foreach ($arr_Input as $input)
					{
						if ($int_I != 0)
						{
							$str_Join = self::C_STR_QUERY_JOIN_AND;
						}

						$this->add_Query($input, $str_Field, $str_Condition, $str_Join);
						$int_I++;
					}
					return;
				}
				if (strpos($str_Input, " " . self::C_STR_QUERY_JOIN_OR . " ") !== false)
				{
					$arr_Input = explode(" " . self::C_STR_QUERY_JOIN_OR . " ", $str_Input);
					$int_I = 0;
					foreach ($arr_Input as $input)
					{
						if ($int_I != 0)
						{
							$str_Join = self::C_STR_QUERY_JOIN_OR;
						}
						$this->add_Query($input, $str_Field, $str_Condition, $str_Join);
						$int_I++;
					}
					return;
				}

				$this->insert_Query($str_Input, $str_Field, $str_Condition, $str_Join);

			}
			else
			{
				$this->insert_Query($str_Input, self::C_STR_QUERY_DEFAULT, $str_Condition, $str_Join);
			}
		}

		function add_Query_Date($str_Field, DateTime $obj_StartDate = null, DateTime $obj_EndDate = null)
		{
			$str_StartDate = "*";
			$str_EndDate = "*";
			if ($obj_StartDate)
			{
				$str_StartDate = $obj_StartDate->format(self::C_STR_FORMAT_DATE);
			}

			if ($obj_EndDate)
			{
				$str_EndDate = $obj_EndDate->format(self::C_STR_FORMAT_DATE);
			}
			$this->add_Query("[" . $str_StartDate . " TO " . $str_EndDate . "]", $str_Field);
		}

		protected function insert_Query($str_Value, $str_Field = self::C_STR_QUERY_DEFAULT, $str_Condition = self::C_STR_QUERY_CONDITION_EQUALS, $str_Join = self::C_STR_QUERY_JOIN_AND)
		{
			$arr_Tmp = array();

			if ($str_Value != "*:*")
			{
				$str_Value = str_ireplace("://", "\\://", $str_Value);
			}

			$arr_Tmp[self::C_STR_QUERY_FIELD] = $str_Field;
			$arr_Tmp[self::C_STR_QUERY_VALUE] = $str_Value;
			$arr_Tmp[self::C_STR_QUERY_JOIN] = $str_Join;
			$arr_Tmp[self::C_STR_QUERY_CONDITION] = $str_Condition;
			$arr_Tmp[self::C_STR_QUERY_TYPE] = self::C_STR_QUERY_TYPE_CONDITION;

			$this->m_obj_InsertPoint[] = $arr_Tmp;
		}

		function add_Query_Range($obj_Start, $obj_End = null, $str_Field = self::C_STR_QUERY_DEFAULT, $str_Join = self::C_STR_QUERY_JOIN_AND)
		{
			$str_Start = "*";
			$str_End = "*";

			if ((!$obj_Start && $obj_Start != "0") && (!$obj_End && $obj_End != "0"))
			{
				return;
			}

			if ($obj_Start || $obj_Start == "0")
			{
				$str_Start = $obj_Start;
			}

			if ($obj_End || $obj_End == "0")
			{
				$str_End = $obj_End;
			}
			$this->add_Query("[" . $str_Start . " TO " . $str_End . "]", $str_Field, self::C_STR_QUERY_CONDITION_EQUALS, $str_Join);

		}

		private function convert_2String($arr_Data)
		{
			//print_r($arr_Data);
			//print("\n");
			$str_Query = "";
			switch ($arr_Data[self::C_STR_QUERY_TYPE])
			{
				case self::C_STR_QUERY_TYPE_CONDITION:
					if (isset($arr_Data[self::C_STR_QUERY_FIELD]) && ($arr_Data[self::C_STR_QUERY_FIELD] != ""))
					{
						$str_Query .= $arr_Data[self::C_STR_QUERY_FIELD] . ":";
					}
					if (isset($arr_Data[self::C_STR_QUERY_VALUE]))
					{
						$str_Query .= $arr_Data[self::C_STR_QUERY_VALUE];
					}
					break;
				case self::C_STR_QUERY_TYPE_GROUP:
					foreach ($arr_Data[self::C_STR_QUERY_CHILDREN] as $arr_Data1)
					{
						$str_Tmp = $this->convert_2String($arr_Data1);
						if ($str_Query)
						{
							$str_Query .= " " . $arr_Data1[self::C_STR_QUERY_JOIN] . " ";
						}

						$str_Query .= $str_Tmp;
					}
					//$str_Query .= "(".$this->convert_2String($arr_Data[self::C_STR_QUERY_CHILDREN]).")";
					break;
			}
			$str_Query = trim($str_Query);
			if ($str_Query != "")
			{
				$str_Query = "(" . $str_Query . ")";
				if (isset($arr_Data[self::C_STR_QUERY_CONDITION]))
				{
					//print($arr_Data[self::C_STR_QUERY_CONDITION]);
					switch ($arr_Data[self::C_STR_QUERY_CONDITION])
					{
						case self::C_STR_QUERY_CONDITION_NOT:
							$str_Query = " NOT " . $str_Query;
							break;
					}
				}
			}

			return $str_Query;
		}

		public function __toString()
		{
			$str_Query = "";

			foreach ($this->arr_Query as $arr_Data)
			{
				$str_Tmp = $this->convert_2String($arr_Data);
				if ($str_Query)
				{
					$str_Query .= " " . $arr_Data[self::C_STR_QUERY_JOIN] . " ";
				}

				$str_Query .= $str_Tmp;
			}
			/*
			 if (isset($this->arr_Query[self::C_STR_QUERY_DEFAULT]))
			 {
			 foreach ($this->arr_Query[self::C_STR_QUERY_DEFAULT] as $arr_Query)
			 {
			 if ($str_Query)
			 {
			 $str_Query .= " " . $arr_Query[self::C_STR_QUERY_JOIN];
			 }
			 $str_Query .= " " . $arr_Query[self::C_STR_QUERY_VALUE];
			 }
			 }
			 foreach ($this->arr_Query as $str_key => $arr_Fields)
			 {
			 if ($str_key != self::C_STR_QUERY_DEFAULT)
			 {
			 foreach ($arr_Fields as $arr_Query)
			 {
			 if ($str_Query)
			 {
			 $str_Query .= " " . $arr_Query[self::C_STR_QUERY_JOIN];
			 }
			 $str_Query .= " " . $str_key . ":" . $arr_Query[self::C_STR_QUERY_VALUE];
			 }
			 }
			 }
																																																			
			 */
			$str_Query = trim($str_Query);
			/*
			 if(empty($str_Query))
			 {
			 $str_Query = "*:*";
			 }
			 */
			return trim($str_Query);
		}
	}
